package ms.unicorn.dsl.eistar.reasoning.maxbelief;

import java.io.File;
import java.util.List;
import java.util.TreeSet;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.Resource.Diagnostic;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.ui.console.MessageConsoleStream;

import eistar.EistarPackage;
import eistar.Entity;
import eistar.EvolutionBranch;
import eistar.EvolutionModel;
import eistar.EvolutionRule;
import eistar.Model;
import eistar.Situation;
import eistar.SubModel;


import ms.unicorn.EIstarStandaloneSetup;
import ms.unicorn.dsl.eistar.util.EistarUtil;
import ms.unicorn.utils.Console;

public class test {

	public static void testEvaluateMaxBelief(Situation sit, String ruleName) {
		Console.printf("testEvaluateMaxBelief(sit = %s, rulename = %s)\n", sit.getName(), ruleName);
		EvolutionRule rule1 = sit.getEntity(ruleName);
		evaluateMaxBelief(rule1);
	}

	public static void evaluateMaxBelief(EvolutionRule rule) {
		MaxBeliefReasoning reasoning = new MaxBeliefReasoning();
		MaxBeliefTable table = reasoning.performReasoning(rule);
		table.printTableContent();
	}
	
	public static void testEvaluateMaxBelief(Situation sit) {
		List<EvolutionModel> emodels = sit.getChildren(EvolutionModel.class);
		Console.printf("Situation %s\n****************\n", sit.getName());
		for(EvolutionModel model: emodels) {
			Console.printf(">> Evaluating evolution model: %s\n", model.getName());
			MaxBeliefReasoning reasoning = new MaxBeliefReasoning();
			MaxBeliefTable table = reasoning.performReasoning(model);
			
			Console.println("Final MaxBelief Table");
			table.printTableContent();
			Console.println();
		}
	}
	
	public static void testEvaluateMaxBelief(EvolutionModel em) {
		Console.printf("testEvaluateMaxBelief(EvolutionModel = %s, Model = %s)\n", em.getName(), em.getModel().getName());
		//EvolutionRule rule = em.combineAllRules();
		//rule.setOriginal(rm);
		//evaluateMaxBelief(rule);
		MaxBeliefReasoning reasoning = new MaxBeliefReasoning();
		MaxBeliefTable table = reasoning.performReasoning(em);
		table.printTableContent();
	}
	
	public static void testCombineRules(EvolutionModel em, Model rm) {
		Console.printf("testCombineRules(EvolutionModel = %s, Model = %s)\n", em.getName(), rm.getName());
		EvolutionRule rule = em.combineAllRules();
		rule.setOriginal(rm);
		printEvolutionRule(rule);
	}

	public static void printEvolutionRule(EvolutionRule rule) {
		List<EvolutionBranch> branches = rule.getAllBranches();
		Console.printf("Rule :%s, %d branches ", rule.getName(), branches.size());
		for(EvolutionBranch b: branches) {
			Console.printf(">>>>Branch:  %s, prob=%d\n", b.getName(), b.getProbability());
			for(Entity e: b.getModelElement(Entity.class)) 
				Console.println(e);
			Console.println("<<<<");
		}
	}
	
	public static Situation loadSituation(String input) {
		ResourceSet rs = new ResourceSetImpl();
		rs.setResourceFactoryRegistry(Resource.Factory.Registry.INSTANCE);

		Resource resource = rs.getResource(URI.createFileURI(input), true);
		EObject eobj = resource.getContents().get(0);
		EList<Diagnostic> errors = resource.getErrors();
		if (errors.size() > 0) {
			for(Diagnostic err: errors) 
				Console.printf("Error: %s", err.getMessage());
			System.exit(1);
		}
		
		return (Situation) eobj;
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		EistarPackage einstance = EistarPackage.eINSTANCE; // register EistarPackage
		new EIstarStandaloneSetup().createInjectorAndDoEMFRegistration();
		//String input = "../rt-unicorn/Test/test2.eis";
		String input = "Test/eis/case2_ex3.eis";
		
		Situation sit = loadSituation(new File(input).getAbsolutePath());
		
		/*MaxBeliefTable tb = new MaxBeliefTable();
		tb.generateFromModel((Model) sit.getEntity("Example2.ERM.rule2.RM8"));
		tb.printTableContent(Console);*/
		
		//testClosure(sit);
		
		//testEvaluateMaxBelief(sit, "EM.EM1.r");
		testEvaluateMaxBelief(sit);
		//testSubModel(sit, "Example2.SM1");
		
		/*printEvolutionRule((EvolutionRule)sit.getEntity("Example2.ERM.rule2"));
		Console.println("---------------------");
		testCombineRules((EvolutionModel)sit.getEntity("Example2.ERM2")
				,(Model)sit.getEntity("Example2.RM"));*/
		
		/*testEvaluateMaxBelief((EvolutionModel)sit.getEntity("Example2.ERM2")
				,(Model)sit.getEntity("Example2.RM"));*/
	}

	public static void testClosure(Situation sit) {
		// Test EistarUtil.findClosure
		Model rm = sit.getEntity("Example2.RM");
		
		TreeSet<Entity> initial = new TreeSet<Entity>();
		initial.add(rm.getChildEntity("G11"));
		TreeSet<Entity> closure = new TreeSet<Entity>();
		
		Console.println("\nREFER TO ME");
		EistarUtil.findClosure(rm.getChildren(), initial, closure, EistarUtil.REFER_TO_ME, null);
		for(Entity e: closure)
			Console.println(e.toString());
		
		Console.println("\nIN CLOSURE");
		closure.clear();
		EistarUtil.findClosure(rm.getChildren(), initial, closure, EistarUtil.IN_CLOSURE, null);
		for(Entity e: closure)
			Console.println(e.toString());
		
		Console.println("\nOUT CLOSURE");
		closure.clear();
		EistarUtil.findClosure(rm.getChildren(), initial, closure, EistarUtil.OUT_CLOSURE, null);
		for(Entity e: closure)
			Console.println(e.toString());
		
		Console.println("\nALL");
		closure.clear();
		EistarUtil.findClosure(rm.getChildren(), initial, closure, EistarUtil.BI_CLOSURE, null);
		for(Entity e: closure)
			Console.println(e.toString());
	}

	public static void testSubModel(Situation sit, String submodel) {
		SubModel sm = sit.getEntity(submodel);
		if (sm != null) {
			Console.println("Submodel:   " + sm.getName());
			Console.println(">>>>BM");
			for(Entity e: sm.getModelElement(Entity.class))
				Console.println(e);
			Console.println("<<<<EM");
		}
	}
}
